﻿// <copyright file="CandidateSummaries.cs" company="Microsoft Corporation">
// Copyright (c) 2009 Microsoft Corporation All Rights Reserved
// </copyright>
// <author>Michael S. Scherotter</author>
// <email>mischero@microsoft.com</email>
// <date>2009-06-10</date>
// <summary>CandidateSummaries class definition</summary>

namespace NYTimes
{
    using System;
    using System.Collections.ObjectModel;
    using System.ComponentModel;
    using System.Globalization;
    using System.Linq;
    using System.Text;
    using NYTimes.Core;
    using NYTimes.Data;    

    /// <summary>
    /// New York Times Campaign Finance Candidate Summaries API
    /// </summary>
    /// <remarks>See <a target="_blank" href="http://developer.nytimes.com/docs/campaign_finance_api#h3-election">Candidate Summaries</a> on the New York Times Developer Network for more information.
    /// </remarks>
    public class CandidateSummaries : CampaignFinance
    {
        #region Fields
        /// <summary>
        /// the campaign year
        /// </summary>
        private int year;
        #endregion

        #region Constructors
        /// <summary>
        /// Initializes a new instance of the CandidateSummaries class.
        /// </summary>
        /// <remarks>If the NYTimesSampleData assembly is in the XAP and this is in design mode, it 
        /// will load CandidateTotals.xml sample data.</remarks>
        public CandidateSummaries()
        {
            this.Results = new ObservableCollection<Candidate>();

            if (SampleData.IsInDesignTool)
            {
                var xml = SampleData.GetSampleData("CandidateTotals.xml");

                this.ParseXml(xml);
            }
        }
        #endregion

        #region Properties
        /// <summary>
        /// Gets or sets the year. (currently 2008 is the only available year and is the default
        /// value)
        /// </summary>
        public int Year
        {
            get
            {
                return this.year;
            }

            set
            {
                if (this.year != value)
                {
                    this.year = value;

                    FetchData();
                }
            }
        }

        /// <summary>
        /// Gets the candidate expenditures and disbursements
        /// </summary>
        public ObservableCollection<Candidate> Results { get; private set; }

        #endregion

        #region Methods
        /// <summary>
        /// Generate the web address
        /// </summary>
        /// <param name="baseAddress">the base address</param>
        /// <returns>the web service URI</returns>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1308:NormalizeStringsToUppercase", Justification = "Not relevant for URI")]
        protected override Uri GenerateAddress(string baseAddress)
        {
            var builder = new StringBuilder(baseAddress);

            builder.AppendFormat(
                CultureInfo.InvariantCulture,
                "{0}/{1}/totals.xml?api-key={2}",
                this.Year,
                this.CampaignType.ToString().ToLowerInvariant(),
                this.ApiKey);

            return new Uri(builder.ToString(), UriKind.Absolute);
        }

        /// <summary>
        /// Clear the candidates collection
        /// </summary>
        protected override void ClearResults()
        {
            this.Results.Clear();
        }

        /// <summary>
        /// Create a <see cref="NYTimes.Data.Candidate"/> object for each candidate element in the 
        /// results.
        /// </summary>
        /// <param name="results">the results element</param>
        /// <returns>true to signify that there are no more results</returns>
        protected override bool ProcessResults(System.Xml.Linq.XElement results)
        {
            if (results == null)
            {
                throw new ArgumentNullException("results");
            }

            var candidates = from candidate in results.Elements("candidate")
                             select new Candidate()
                             {
                                 DateCoverageTo = DateTime.Parse(candidate.Element("date_coverage_to").Value, CultureInfo.InvariantCulture),
                                 Name = candidate.Element("candidate_name").Value,
                                 Party = candidate.Element("party").Value,
                                 TotalDisbursements = double.Parse(candidate.Element("total_disbursements").Value, CultureInfo.InvariantCulture),
                                 TotalReceipts = double.Parse(candidate.Element("total_receipts").Value, CultureInfo.InvariantCulture)
                             };

            foreach (var candidate in candidates)
            {
                this.Results.Add(candidate);
            }

            return true;
        }

        #endregion
    }
}
